home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk.zip / EXECUTE.C < prev    next >
C/C++ Source or Header  |  1991-04-09  |  27KB  |  928 lines

  1.  
  2. /********************************************
  3. execute.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the Awk programming language as defined in
  8. Aho, Kernighan and Weinberger, The AWK Programming Language,
  9. Addison-Wesley, 1988.
  10.  
  11. See the accompaning file, LIMITATIONS, for restrictions
  12. regarding modification and redistribution of this
  13. program in source or binary form.
  14. ********************************************/
  15.  
  16. /* $Log:    execute.c,v $
  17.  * Revision 2.2  91/04/09  12:38:54  brennan
  18.  * added static to funct decls to satisfy STARDENT compiler
  19.  * 
  20.  * Revision 2.1  91/04/08  08:22:55  brennan
  21.  * VERSION 0.97
  22.  * 
  23. */
  24.  
  25.  
  26. #include "mawk.h"
  27. #include "code.h"
  28. #include "memory.h"
  29. #include "symtype.h"
  30. #include "field.h"
  31. #include "bi_funct.h"
  32. #include "regexp.h"
  33. #include "repl.h"
  34. #include <math.h>
  35.  
  36. /* static functions */
  37. static int PROTO( compare, (CELL *) ) ;
  38. static void PROTO( eval_overflow, (void) ) ;
  39.  
  40. #ifdef   DEBUG
  41. #define  inc_sp()   if( ++sp == eval_stack+EVAL_STACK_SIZE )\
  42.                          eval_overflow()
  43. #else
  44.  
  45. /* If things are working, the only reason the eval stack should
  46.    overflow is too much function recursion
  47.    (checked for at _CALL below  */
  48.  
  49. #define inc_sp()    sp++
  50. #endif
  51.  
  52. #define  SAFETY    3    /* if we get within 3 of stack top emit 
  53.          overflow */
  54.  
  55. /*  The stack machine that executes the code */
  56.  
  57. CELL  eval_stack[EVAL_STACK_SIZE] ;
  58.  
  59. static void eval_overflow()
  60. { overflow("eval stack" , EVAL_STACK_SIZE) ; mawk_exit(1) ; }
  61.  
  62. /* if this flag is on, recursive calls to execute need to
  63.    return to the _CALL statement.  This only happens
  64.    inside array loops */
  65. int  returning ;  
  66.  
  67. INST  *execute(cdp, sp, fp)
  68.   register INST *cdp ;  /* code ptr, start execution here */
  69.   register CELL *sp ;   /* eval_stack pointer */
  70.   CELL *fp ;            /* frame ptr into eval_stack for
  71.                            user defined functions */
  72.   /* some useful temporaries */
  73.   CELL *cp , tc ;
  74.   int t ;
  75.  
  76. #ifdef  DEBUG
  77.   CELL *entry_sp = sp ;
  78. #endif
  79.  
  80.   while ( 1 )
  81.     switch( cdp++ -> op )
  82.     {   case  _HALT :
  83.         case  _STOP :  
  84.  
  85. #ifdef   DEBUG
  86. /* check the stack is sane */
  87.                 if ( sp != entry_sp ) bozo("stop") ;
  88.                 return cdp - 1 ;
  89.  
  90.         case  _STOP0  : /* if debugging stops range patterns */
  91.                 if ( sp != entry_sp+1 ) bozo("stop0") ;
  92. #else
  93.         case  _STOP0  :
  94. #endif
  95.                 return cdp -  1 ;
  96.  
  97.         case  _PUSHC :  
  98.             inc_sp() ;
  99.             (void) cellcpy(sp, cdp++ -> ptr) ;
  100.             break ;
  101.  
  102.         case  F_PUSHA :
  103.             if ( (CELL*)cdp->ptr != field && nf < 0 ) split_field0() ;
  104.             /* fall thru */
  105.  
  106.         case  _PUSHA :
  107.         case  A_PUSHA :
  108.             inc_sp() ;
  109.             sp -> ptr = cdp++ -> ptr ;
  110.             break ;
  111.  
  112.         case _PUSHI :  /* put contents of next address on stack*/
  113.             inc_sp() ;
  114.             (void) cellcpy(sp, cdp++ -> ptr) ;
  115.             break ;
  116.             
  117.         case L_PUSHI :  
  118.             /* put the contents of a local var on stack,
  119.                cdp->op holds the offset from the frame pointer */
  120.             inc_sp() ;
  121.             (void) cellcpy(sp, fp + cdp++->op) ;
  122.             break ;
  123.  
  124.         case L_PUSHA : /* put a local address on eval stack */
  125.             inc_sp() ;
  126.             sp->ptr = (PTR)(fp + cdp++->op) ;
  127.             break ;
  128.  
  129.  
  130.         case F_PUSHI :
  131.  
  132.         /* note $0 , RS , FS and OFMT are loaded by _PUSHI */
  133.  
  134.             inc_sp() ;
  135.             if ( nf < 0 )  split_field0() ;
  136.             if ( (t = (CELL *) cdp->ptr - field) <= nf ||
  137.                   t == NF  )
  138.             { (void) cellcpy(sp, cdp++ -> ptr) ; }
  139.             else  /* an unset field */
  140.             { sp->type = C_STRING ;
  141.               sp->ptr = (PTR) & null_str ;
  142.               null_str.ref_cnt++ ;
  143.               cdp++ ;
  144.             }
  145.             break ;
  146.  
  147.         case  FE_PUSHA :
  148.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  149.             if ( (t = (int) sp->dval) < 0 )
  150.                 rt_error( "negative field index(%d)", t) ;
  151.             if ( t > MAX_FIELD )
  152.                 rt_overflow("MAX_FIELD", MAX_FIELD) ;
  153.             if ( t && nf < 0 )  split_field0() ;
  154.             sp->ptr = (PTR) &field[t] ;
  155.             break ;
  156.  
  157.         case  FE_PUSHI :
  158.             if ( sp->type != C_DOUBLE )  cast1_to_d(sp) ;
  159.  
  160.             if ( (t = (int) sp->dval) == 0 )
  161.             { (void) cellcpy(sp, &field[0]) ; break ; }
  162.  
  163.             if ( t < 0 )
  164.                   rt_error( "negative field index(%d)", t) ;
  165.             if ( t > MAX_FIELD )
  166.                   rt_overflow("MAX_FIELD", MAX_FIELD) ;
  167.  
  168.             if ( nf < 0)  split_field0() ;
  169.             if ( t <= nf ) (void) cellcpy(sp, &field[t]) ;
  170.             else
  171.             { sp->type = C_STRING ;
  172.               sp->ptr = (PTR) & null_str ;
  173.               null_str.ref_cnt++ ;
  174.             }
  175.             break ; 
  176.  
  177.  
  178.         case  AE_PUSHA :
  179.         /* top of stack has an expr, cdp->ptr points at an
  180.            array, replace the expr with the cell address inside
  181.            the array */
  182.             cast1_to_s(sp) ;
  183.             cp = array_find((ARRAY)cdp++->ptr, sp->ptr, 0) ;
  184.             free_STRING( string(sp) );
  185.             sp->ptr = (PTR) cp ;
  186.             break ;
  187.  
  188.         case  AE_PUSHI :
  189.         /* top of stack has an expr, cdp->ptr points at an
  190.            array, replace the expr with the contents of the
  191.            cell inside the array */
  192.             cast1_to_s(sp) ;
  193.             cp = array_find((ARRAY) cdp++->ptr, sp->ptr, 0) ;
  194.             free_STRING(string(sp)) ;
  195.             (void) cellcpy(sp, cp) ;
  196.             break ;
  197.  
  198.         case  LAE_PUSHI :
  199.         /*  sp[0] is an expression
  200.             cdp->op is offset from frame pointer of a CELL which
  201.                has an ARRAY in the ptr field, replace expr
  202.             with  array[expr]
  203.         */
  204.             cast1_to_s(sp) ;
  205.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp->ptr, 0) ;
  206.             free_STRING(string(sp)) ;
  207.             (void) cellcpy(sp, cp) ;
  208.             break ;
  209.             
  210.         case  LAE_PUSHA :
  211.         /*  sp[0] is an expression
  212.             cdp->op is offset from frame pointer of a CELL which
  213.                has an ARRAY in the ptr field, replace expr
  214.             with  & array[expr]
  215.         */
  216.             cast1_to_s(sp) ;
  217.             cp = array_find( (ARRAY)fp[cdp++->op].ptr, sp->ptr, 0) ;
  218.             free_STRING(string(sp)) ;
  219.             sp->ptr = (PTR) cp ;
  220.             break ;
  221.             
  222.         case  LA_PUSHA  :
  223.         /*  cdp->op is offset from frame pointer of a CELL which
  224.                has an ARRAY in the ptr field. Push this ARRAY
  225.                on the eval stack
  226.         */
  227.             inc_sp() ;
  228.             sp->ptr = fp[cdp++->op].ptr ;
  229.             break ;
  230.  
  231.         case  A_LOOP :
  232.             cdp = array_loop(cdp,sp,fp) ;
  233.             if ( returning ) return cdp ; /*value doesn't matter*/
  234.             sp -= 2 ;
  235.             break ;
  236.  
  237.         case  _POP : 
  238.             cell_destroy(sp) ;
  239.             sp-- ;
  240.             break ;
  241.  
  242.         case _DUP  :
  243.             (void) cellcpy(sp+1, sp) ;
  244.             sp++ ; break ;
  245.  
  246.         case  _ASSIGN :
  247.             /* top of stack has an expr, next down is an
  248.                address, put the expression in *address and
  249.                replace the address with the expression */
  250.  
  251.             /* don't propagate type C_MBSTRN */
  252.             if ( sp->type == C_MBSTRN ) check_strnum(sp) ;
  253.             sp-- ;
  254.             cell_destroy( ((CELL *)sp->ptr) ) ;
  255.             (void) cellcpy( sp, cellcpy(sp->ptr, sp+1) ) ;
  256.             cell_destroy(sp+1) ;
  257.             break ;
  258.  
  259.         case  F_ASSIGN : /* assign to a field  */
  260.             if (sp->type == C_MBSTRN) check_strnum(sp) ;
  261.             sp-- ;
  262.             field_assign((CELL*)sp->ptr - field, sp+1) ;
  263.             cell_destroy(sp+1) ;
  264.             (void) cellcpy(sp, (CELL *) sp->ptr) ;
  265.             break ;
  266.  
  267.         case  _ADD_ASG:
  268.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  269.             cp = (CELL *) (sp-1)->ptr ;
  270.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  271.             cp->dval += sp-- -> dval ;
  272.             sp->type = C_DOUBLE ;
  273.             sp->dval = cp->dval ;
  274.             break ;
  275.  
  276.         case  _SUB_ASG:
  277.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  278.             cp = (CELL *) (sp-1)->ptr ;
  279.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  280.             cp->dval -= sp-- -> dval ;
  281.             sp->type = C_DOUBLE ;
  282.             sp->dval = cp->dval ;
  283.             break ;
  284.  
  285.         case  _MUL_ASG:
  286.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  287.             cp = (CELL *) (sp-1)->ptr ;
  288.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  289.             cp->dval *= sp-- -> dval ;
  290.             sp->type = C_DOUBLE ;
  291.             sp->dval = cp->dval ;
  292.             break ;
  293.  
  294.         case  _DIV_ASG:
  295.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  296.             cp = (CELL *) (sp-1)->ptr ;
  297.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  298.             cp->dval /= sp-- -> dval ;
  299.             sp->type = C_DOUBLE ;
  300.             sp->dval = cp->dval ;
  301.             break ;
  302.  
  303.         case  _MOD_ASG:
  304.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  305.             cp = (CELL *) (sp-1)->ptr ;
  306.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  307.             cp->dval = fmod(cp->dval,sp-- -> dval) ;
  308.             sp->type = C_DOUBLE ;
  309.             sp->dval = cp->dval ;
  310.             break ;
  311.  
  312.         case  _POW_ASG:
  313.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  314.             cp = (CELL *) (sp-1)->ptr ;
  315.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  316.             cp->dval = pow(cp->dval,sp-- -> dval) ;
  317.             sp->type = C_DOUBLE ;
  318.             sp->dval = cp->dval ;
  319.             break ;
  320.  
  321.         /* will anyone ever use these ? */
  322.  
  323.         case F_ADD_ASG :
  324.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  325.             cp = (CELL *) (sp-1)->ptr ;
  326.             cast1_to_d( cellcpy(&tc, cp) ) ;
  327.             tc.dval += sp-- -> dval ;
  328.             sp->type = C_DOUBLE ;
  329.             sp->dval = tc.dval ;
  330.             field_assign(cp-field, &tc) ;
  331.             break ;
  332.  
  333.         case F_SUB_ASG :
  334.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  335.             cp = (CELL *) (sp-1)->ptr ;
  336.             cast1_to_d( cellcpy(&tc, cp) ) ;
  337.             tc.dval -= sp-- -> dval ;
  338.             sp->type = C_DOUBLE ;
  339.             sp->dval = tc.dval ;
  340.             field_assign(cp-field, &tc) ;
  341.             break ;
  342.  
  343.         case F_MUL_ASG :
  344.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  345.             cp = (CELL *) (sp-1)->ptr ;
  346.             cast1_to_d( cellcpy(&tc, cp) ) ;
  347.             tc.dval *= sp-- -> dval ;
  348.             sp->type = C_DOUBLE ;
  349.             sp->dval = tc.dval ;
  350.             field_assign(cp-field, &tc) ;
  351.             break ;
  352.  
  353.         case F_DIV_ASG :
  354.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  355.             cp = (CELL *) (sp-1)->ptr ;
  356.             cast1_to_d( cellcpy(&tc, cp) ) ;
  357.             tc.dval /= sp-- -> dval ;
  358.             sp->type = C_DOUBLE ;
  359.             sp->dval = tc.dval ;
  360.             field_assign(cp-field, &tc) ;
  361.             break ;
  362.  
  363.         case F_MOD_ASG :
  364.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  365.             cp = (CELL *) (sp-1)->ptr ;
  366.             cast1_to_d( cellcpy(&tc, cp) ) ;
  367.             tc.dval = fmod(tc.dval, sp-- -> dval) ;
  368.             sp->type = C_DOUBLE ;
  369.             sp->dval = tc.dval ;
  370.             field_assign(cp-field, &tc) ;
  371.             break ;
  372.  
  373.         case F_POW_ASG :
  374.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  375.             cp = (CELL *) (sp-1)->ptr ;
  376.             cast1_to_d( cellcpy(&tc, cp) ) ;
  377.             tc.dval = pow(tc.dval, sp-- -> dval) ;
  378.             sp->type = C_DOUBLE ;
  379.             sp->dval = tc.dval ;
  380.             field_assign(cp-field, &tc) ;
  381.             break ;
  382.  
  383.         case _ADD :
  384.             sp-- ;
  385.             if ( TEST2(sp) != TWO_DOUBLES )
  386.                     cast2_to_d(sp) ;
  387.             sp[0].dval += sp[1].dval ;
  388.             break ;
  389.  
  390.         case _SUB :
  391.             sp-- ;
  392.             if ( TEST2(sp) != TWO_DOUBLES )
  393.                     cast2_to_d(sp) ;
  394.             sp[0].dval -= sp[1].dval ;
  395.             break ;
  396.  
  397.         case _MUL :
  398.             sp-- ;
  399.             if ( TEST2(sp) != TWO_DOUBLES )
  400.                     cast2_to_d(sp) ;
  401.             sp[0].dval *= sp[1].dval ;
  402.             break ;
  403.  
  404.         case _DIV :
  405.             sp-- ;
  406.             if ( TEST2(sp) != TWO_DOUBLES )
  407.                     cast2_to_d(sp) ;
  408.             sp[0].dval /= sp[1].dval ;
  409.             break ;
  410.  
  411.         case _MOD :
  412.             sp-- ;
  413.             if ( TEST2(sp) != TWO_DOUBLES )
  414.                     cast2_to_d(sp) ;
  415.             sp[0].dval = fmod(sp[0].dval,sp[1].dval) ;
  416.             break ;
  417.  
  418.         case _POW :
  419.             sp-- ;
  420.             if ( TEST2(sp) != TWO_DOUBLES )
  421.                     cast2_to_d(sp) ;
  422.             sp[0].dval = pow(sp[0].dval,sp[1].dval) ;
  423.             break ;
  424.  
  425.         case _NOT :
  426.         reswitch_1:
  427.             switch( sp->type )
  428.             { case C_NOINIT :
  429.                     sp->dval = 1.0 ; break ;
  430.               case C_DOUBLE :
  431.                     sp->dval =  sp->dval ? 0.0 : 1.0 ;
  432.                     break ;
  433.               case C_STRING :
  434.                     sp->dval = string(sp)->len ? 0.0 : 1.0 ;
  435.                     free_STRING(string(sp)) ;
  436.                     break ;
  437.               case C_STRNUM : /* test as a number */
  438.                     sp->dval = sp->dval ? 0.0 : 1.0 ;
  439.                     free_STRING(string(sp)) ;
  440.                     break ;
  441.               case C_MBSTRN :
  442.                     check_strnum(sp) ;
  443.                     goto reswitch_1 ;
  444.               default :
  445.                     bozo("bad type on eval stack") ;
  446.             }
  447.             sp->type = C_DOUBLE ;
  448.             break  ;
  449.  
  450.         case _TEST :
  451.         reswitch_2:
  452.             switch( sp->type )
  453.             { case C_NOINIT :
  454.                     sp->dval = 0.0 ; break ;
  455.               case C_DOUBLE :
  456.                     sp->dval = sp->dval ? 1.0 : 0.0 ;
  457.                     break ;
  458.               case C_STRING :
  459.                     sp->dval  = string(sp)->len ? 1.0 : 0.0 ;
  460.                     free_STRING(string(sp)) ;
  461.                     break ;
  462.               case C_STRNUM : /* test as a number */
  463.                     sp->dval  = sp->dval ? 0.0 : 1.0 ;
  464.                     free_STRING(string(sp)) ;
  465.                     break ;
  466.               case C_MBSTRN :
  467.                     check_strnum(sp) ;
  468.                     goto reswitch_2 ;
  469.               default :
  470.                     bozo("bad type on eval stack") ;
  471.             }
  472.             sp->type = C_DOUBLE ;
  473.             break ;
  474.  
  475.         case _UMINUS :
  476.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  477.             sp->dval = - sp->dval ;
  478.             break ;
  479.  
  480.         case _UPLUS :  
  481.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  482.             break ;
  483.  
  484.         case _CAT :
  485.             { unsigned len1, len2 ;
  486.               char *str1, *str2 ;
  487.               STRING *b ;
  488.               
  489.               sp-- ;
  490.               if ( TEST2(sp) != TWO_STRINGS )
  491.                     cast2_to_s(sp) ;
  492.               str1 = string(sp)->str ;
  493.               len1 = string(sp)->len ;
  494.               str2 = string(sp+1)->str ;
  495.               len2 = string(sp+1)->len ;
  496.  
  497.               b = new_STRING((char *)0, len1+len2) ;
  498.               (void) memcpy(b->str, str1, len1) ;
  499.               (void) memcpy(b->str + len1, str2, len2) ;
  500.               free_STRING(string(sp)) ;
  501.               free_STRING( string(sp+1) ) ;
  502.  
  503.               sp->ptr = (PTR) b ;
  504.               break ;
  505.             }
  506.  
  507.         case _PUSHINT :
  508.             inc_sp() ;
  509.             sp->type = cdp++ -> op ;
  510.             break ;
  511.  
  512.         case _BUILTIN :
  513.         case _PRINT :
  514.             sp = (* (PF_CP) cdp++ -> ptr) (sp) ;
  515.             break ;
  516.  
  517.         case _POST_INC :
  518.             (void) cellcpy(sp, cp = (CELL *)sp->ptr) ;
  519.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  520.             cp->dval += 1.0 ;
  521.             break ;
  522.  
  523.         case _POST_DEC :
  524.             (void) cellcpy(sp, cp = (CELL *)sp->ptr) ;
  525.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  526.             cp->dval -= 1.0 ;
  527.             break ;
  528.  
  529.         case _PRE_INC :
  530.             cp = (CELL *) sp->ptr ;
  531.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  532.             sp->dval = cp->dval += 1.0 ;
  533.             sp->type = C_DOUBLE ;
  534.             break ;
  535.  
  536.         case _PRE_DEC :
  537.             cp = (CELL *) sp->ptr ;
  538.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  539.             sp->dval = cp->dval -= 1.0 ;
  540.             sp->type = C_DOUBLE ;
  541.             break ;
  542.  
  543.  
  544.         case F_POST_INC  :
  545.             cp = (CELL *) sp->ptr ;
  546.             (void) cellcpy(sp, cellcpy(&tc, cp) ) ;
  547.             cast1_to_d(&tc) ;
  548.             tc.dval += 1.0 ;
  549.             field_assign(cp-field, &tc) ;
  550.             break ;
  551.  
  552.         case F_POST_DEC  :
  553.             cp = (CELL *) sp->ptr ;
  554.             (void) cellcpy(sp, cellcpy(&tc, cp) ) ;
  555.             cast1_to_d(&tc) ;
  556.             tc.dval -= 1.0 ;
  557.             field_assign(cp-field, &tc) ;
  558.             break ;
  559.  
  560.         case F_PRE_INC :
  561.             cp = (CELL *) sp->ptr ;
  562.             cast1_to_d(cellcpy(&tc, cp)) ;
  563.             sp->dval = tc.dval += 1.0 ;
  564.             sp->type = C_DOUBLE ;
  565.             field_assign(cp-field, sp) ;
  566.             break ;
  567.  
  568.         case F_PRE_DEC :
  569.             cp = (CELL *) sp->ptr ;
  570.             cast1_to_d(cellcpy(&tc, cp)) ;
  571.             sp->dval = tc.dval -= 1.0 ;
  572.             sp->type = C_DOUBLE ;
  573.             field_assign(cp-field, sp) ;
  574.             break ;
  575.  
  576.         case _JMP  :
  577.             cdp += cdp->op - 1 ;
  578.             break ;
  579.  
  580.         case _JNZ  :
  581.             /* jmp if top of stack is non-zero and pop stack */
  582.             if ( test( sp ) )
  583.                 cdp += cdp->op - 1 ;
  584.             else  cdp++ ;
  585.             cell_destroy(sp) ;
  586.             sp-- ;
  587.             break ;
  588.  
  589.         case _JZ  :
  590.             /* jmp if top of stack is zero and pop stack */
  591.             if ( ! test( sp ) )
  592.                 cdp += cdp->op - 1 ;
  593.             else  cdp++ ;
  594.             cell_destroy(sp) ;
  595.             sp-- ;
  596.             break ;
  597.  
  598.     /*  the relation operations */
  599.     /*  compare() makes sure string ref counts are OK */
  600.         case  _EQ :
  601.             t = compare(--sp) ;
  602.             sp->type = C_DOUBLE ;
  603.             sp->dval = t == 0 ? 1.0 : 0.0 ;
  604.             break ;
  605.  
  606.         case  _NEQ :
  607.             t = compare(--sp) ;
  608.             sp->type = C_DOUBLE ;
  609.             sp->dval = t ? 1.0 : 0.0 ;
  610.             break ;
  611.  
  612.         case  _LT :
  613.             t = compare(--sp) ;
  614.             sp->type = C_DOUBLE ;
  615.             sp->dval = t < 0 ? 1.0 : 0.0 ;
  616.             break ;
  617.  
  618.         case  _LTE :
  619.             t = compare(--sp) ;
  620.             sp->type = C_DOUBLE ;
  621.             sp->dval = t <= 0 ? 1.0 : 0.0 ;
  622.             break ;
  623.  
  624.         case  _GT :
  625.             t = compare(--sp) ;
  626.             sp->type = C_DOUBLE ;
  627.             sp->dval = t > 0 ? 1.0 : 0.0 ;
  628.             break ;
  629.  
  630.         case  _GTE :
  631.             t = compare(--sp) ;
  632.             sp->type = C_DOUBLE ;
  633.             sp->dval = t >= 0 ? 1.0 : 0.0 ;
  634.             break ;
  635.  
  636.         case  _MATCH :
  637.             /* does sp[-1] match sp[0] as re */
  638.             if ( sp->type != C_RE )  cast_to_RE(sp) ;
  639.  
  640.             if ( (--sp)->type < C_STRING )  cast1_to_s(sp) ;
  641.             t = REtest(string(sp)->str, (sp+1)->ptr) ; 
  642.  
  643.             free_STRING(string(sp)) ;
  644.             sp->type = C_DOUBLE ;
  645.             sp->dval = t ? 1.0 : 0.0 ;
  646.             break ;
  647.  
  648.         case  A_TEST :
  649.         /* entry :  sp[0].ptr-> an array
  650.                     sp[-1]  is an expression
  651.  
  652.            we compute   expression in array  */
  653.             if ( (--sp)->type < C_STRING ) cast1_to_s(sp) ;
  654.             t = array_test( (sp+1)->ptr, string(sp)) ;
  655.             free_STRING(string(sp)) ;
  656.             sp->type = C_DOUBLE ;
  657.             sp->dval = t ? 1.0 : 0.0 ;
  658.             break ;
  659.  
  660.         case  A_DEL :
  661.         /* sp[0].ptr ->  array)
  662.            sp[-1] is an expr
  663.            delete  array[expr]  */
  664.  
  665.             cast1_to_s(--sp) ;
  666.             array_delete( sp[1].ptr , sp->ptr) ;
  667.             free_STRING( string(sp) ) ;
  668.             sp-- ;
  669.             break ;
  670.         
  671.         /* form a multiple array index */
  672.         case A_CAT :
  673.             sp = array_cat(sp, cdp++->op) ;
  674.             break ;
  675.  
  676.         case  _EXIT0 :
  677.             longjmp( exit_jump, 1) ;
  678.  
  679.         case  _EXIT  :
  680.             if ( sp->type != C_DOUBLE ) cast1_to_d(sp) ;
  681.             exit_code = (int) sp->dval ;
  682.             longjmp( exit_jump, 1) ;
  683.  
  684.         case  _NEXT :
  685.             longjmp(next_jump, 1) ;
  686.  
  687.         case  _RANGE :
  688. /* test a range pattern:  pat1, pat2 { action }
  689.    entry :
  690.        cdp[0].op -- a flag, test pat1 if on else pat2
  691.        cdp[1].op -- offset of pat2 code from cdp
  692.        cdp[2].op -- offset of action code from cdp
  693.        cdp[3].op -- offset of code after the action from cdp
  694.        cdp[4] -- start of pat1 code
  695. */
  696.  
  697. #define FLAG    cdp[0].op
  698. #define PAT2    cdp[1].op
  699. #define ACTION    cdp[2].op
  700. #define FOLLOW    cdp[3].op
  701. #define PAT1      4
  702.  
  703.             if ( FLAG )  /* test again pat1 */
  704.             { 
  705.               (void) execute(cdp + PAT1,sp, fp) ;
  706.               t = test(sp+1) ;
  707.               cell_destroy(sp+1) ;
  708.               if ( t )  FLAG = 0 ;
  709.               else
  710.               { cdp += FOLLOW ;
  711.                 break ;  /* break the switch */
  712.               }
  713.             }
  714.  
  715.             /* test against pat2 and then perform the action */
  716.             (void) execute(cdp + PAT2, sp, fp) ;
  717.             FLAG  = test(sp+1) ;
  718.             cell_destroy(sp+1) ; 
  719.             cdp += ACTION ;
  720.             break ;
  721.  
  722. /* function calls  */
  723.  
  724.       case  _RET0  :
  725.             inc_sp() ;
  726.             sp->type = C_NOINIT ;
  727.             /* fall thru */
  728.  
  729.       case  _RET   :
  730.  
  731. #ifdef  DEBUG
  732.             if ( sp != entry_sp+1 ) bozo("ret") ;
  733. #endif
  734.             returning = 1 ;
  735.             return  cdp-1 ;
  736.  
  737.       case  _CALL  :
  738.  
  739.             { FBLOCK *fbp = (FBLOCK*) cdp++->ptr ;
  740.               int a_args = cdp++->op ; /* actual number of args */
  741.               CELL *nfp = sp - a_args + 1 ; /* new fp for callee */
  742.               CELL *local_p = sp+1; /* first local argument on stack */
  743.               char *type_p ;  /* pts to type of an argument */
  744.  
  745.               if ( fbp->nargs ) type_p = fbp->typev + a_args ;
  746.  
  747.               /* create space for locals */
  748.               if ( t = fbp->nargs - a_args ) /* have local args */
  749.               {
  750.                 if ( sp + t >= eval_stack + EVAL_STACK_SIZE - SAFETY )
  751.                    eval_overflow() ;
  752.  
  753.                 while ( t-- )  
  754.                 { (++sp)->type = C_NOINIT ;
  755.                   if ( *type_p++ == ST_LOCAL_ARRAY )
  756.                         sp->ptr = (PTR) new_ARRAY() ;
  757.                 }
  758.               }
  759.               type_p-- ; /* *type_p is type of last arg */ 
  760.  
  761.               (void) execute(fbp->code, sp, nfp) ;
  762. #ifdef  DEBUG
  763. if ( !returning )  bozo("call") ;
  764. #endif
  765.               returning = 0 ;
  766.  
  767.               /* cleanup the callee's arguments */
  768.               if ( sp >= nfp ) 
  769.               {
  770.                 cp = sp+1 ;  /* cp -> the function return */
  771.  
  772.                 do
  773.                 {
  774.                   if ( *type_p-- == ST_LOCAL_ARRAY )
  775.                   {  if ( sp >= local_p ) array_free(sp->ptr) ; }
  776.                   else  cell_destroy(sp) ;
  777.  
  778.                 } while ( --sp >= nfp ) ;
  779.                     
  780.                 (void) cellcpy(++sp, cp) ;
  781.                 cell_destroy(cp) ;
  782.               }
  783.               else  sp++ ; /* no arguments passed */
  784.             }
  785.             break ;
  786.  
  787.         default :
  788.             bozo("bad opcode") ;
  789.     }
  790. }
  791.  
  792. int test( cp )  /* test if a cell is null or not */
  793.   register CELL *cp ;
  794. reswitch :
  795.  
  796.   switch ( cp->type )
  797.   {
  798.     case C_NOINIT :  return  0 ;
  799.     case C_STRNUM :  /* test as a number */
  800.     case C_DOUBLE :  return  cp->dval != 0.0 ;
  801.     case C_STRING :  return  string(cp)->len ;
  802.     case C_MBSTRN :  check_strnum(cp) ; goto reswitch ;
  803.  
  804.     default :
  805.       bozo("bad cell type in call to test") ;
  806.   }
  807. }
  808.  
  809. /* compare cells at cp and cp+1 and
  810.    frees STRINGs at those cells
  811. */
  812.  
  813. static int compare(cp)
  814.   register CELL *cp ;
  815. { int k ;
  816.  
  817. reswitch :
  818.  
  819.   switch( TEST2(cp) )
  820.   { case TWO_NOINITS :  return 0 ; 
  821.     
  822.     case TWO_DOUBLES :
  823.     two_d:
  824.             return  cp->dval > (cp+1)->dval ? 1 :
  825.                     cp->dval < (cp+1)->dval ? -1 : 0 ;
  826.     
  827.     case TWO_STRINGS :
  828.     case STRING_AND_STRNUM :
  829.     two_s:
  830.             k = strcmp(string(cp)->str, string(cp+1)->str) ;
  831.             free_STRING( string(cp) ) ;
  832.             free_STRING( string(cp+1) ) ;
  833.             return k ;
  834.  
  835.     case  NOINIT_AND_DOUBLE  :
  836.     case  NOINIT_AND_STRNUM  :
  837.     case  DOUBLE_AND_STRNUM  :
  838.     case TWO_STRNUMS :
  839.             cast2_to_d(cp) ; goto two_d ;
  840.  
  841.     case  NOINIT_AND_STRING  :
  842.     case  DOUBLE_AND_STRING  :
  843.             cast2_to_s(cp) ; goto two_s ;
  844.  
  845.     case  TWO_MBSTRNS :
  846.             check_strnum(cp) ; check_strnum(cp+1) ;
  847.             goto reswitch ;
  848.  
  849.     case  NOINIT_AND_MBSTRN :
  850.     case  DOUBLE_AND_MBSTRN :
  851.     case  STRING_AND_MBSTRN :
  852.     case  STRNUM_AND_MBSTRN :
  853.             check_strnum( cp->type == C_MBSTRN ? cp : cp+1 ) ;
  854.             goto reswitch ;
  855.  
  856.     default :  /* there are no default cases */
  857.             bozo("bad cell type passed to compare") ;
  858.   }
  859. }
  860.  
  861. /* does not assume target was a cell, if so
  862.    then caller should have made a previous
  863.    call to cell_destroy  */
  864.  
  865. CELL *cellcpy(target, source)
  866.   register CELL *target, *source ;
  867. { switch( target->type = source->type )
  868.   { case C_NOINIT : 
  869.     case C_SPACE  : 
  870.     case C_SNULL  :
  871.             break ;
  872.  
  873.     case C_DOUBLE :
  874.             target->dval = source->dval ;
  875.             break ;
  876.  
  877.     case C_STRNUM :
  878.             target->dval = source->dval ;
  879.             /* fall thru */
  880.  
  881.     case C_REPL    :
  882.     case C_MBSTRN  :
  883.     case C_STRING  :
  884.             string(source)->ref_cnt++ ;
  885.             /* fall thru */
  886.  
  887.     case C_RE  :
  888.             target->ptr = source->ptr ;
  889.             break ;
  890.  
  891.     case  C_REPLV :
  892.             (void)  replv_cpy(target, source) ;
  893.             break ;
  894.  
  895.     default :
  896.             bozo("bad cell passed to cellcpy()") ;
  897.             break ;
  898.   }
  899.   return  target ;
  900. }
  901.  
  902. #ifdef   DEBUG
  903.  
  904. void  DB_cell_destroy(cp)    /* HANGOVER time */
  905.   register CELL *cp ;
  906. {
  907.   switch( cp->type )
  908.   { case C_NOINIT :
  909.     case C_DOUBLE :  break ;
  910.  
  911.     case C_MBSTRN :
  912.     case C_STRING :
  913.     case C_STRNUM :
  914.             if ( -- string(cp)->ref_cnt == 0 )
  915.                 zfree(string(cp) , string(cp)->len+5) ;
  916.             break ;
  917.  
  918.     case  C_RE :
  919.             bozo("cell destroy called on RE cell") ;
  920.     default :
  921.             bozo("cell destroy called on bad cell type") ;
  922.   }
  923. }
  924.  
  925. #endif
  926.